#ifndef __CONTROLLER_H__
#define __CONTROLLER_H__

#include "membackend/accurateAddressMappingConfig.h"
#include "membackend/accurateBank.h"
#include "membackend/accurateCommand.h"
#include "membackend/accurateRank.h"
#include "membackend/accurateTransaction.h"
#include "membackend/accurateTransactionQueue.h"
#include <algorithm>









class Controller
{
private:
    /* data */
    uint64_t clock_cycle;
    uint64_t trans_id;
    

    AddressMappingConfig* m_addressMappingConfig; // Pointer to address mapping configuration


    uint64_t m_numRanks;
    uint64_t m_numBanks;
    uint64_t m_numBankGroups;
    std::vector<Rank> m_ranksVector;

    uint64_t trans_queue_size;

    vector<Transaction> read_transactions;
    vector<Transaction> write_transactions;
    vector<Transaction> return_transactions;

    // 写排空
    uint64_t is_draining; // Flag to indicate if the controller is draining

    unordered_map<uint64_t, Transaction> all_transactions; // Maps transaction ID to Transaction object
    unordered_map<uint64_t, vector<Transaction>> pending_reads;
    unordered_map<uint64_t, vector<Transaction>> pending_writes;

    TransactionQueue transaction_queue;
    CommandQueue cmd_queue;

public:
    Controller();
    Controller(AddressMappingConfig* amp);
    int Init(); // Placeholder for initialization logic
    ~Controller();
    void Clock(uint64_t cycle);
    bool WillAcceptTransaction(bool isWrite);
    bool WillAcceptCommand(uint64_t rank_id, uint64_t bank_group_id, uint64_t bank_id) {
        return cmd_queue.WillAcceptCommand(rank_id, bank_group_id, bank_id);
    }
    bool AddTransaction(uint64_t id, uint64_t address, bool isWrite);
    uint64_t GetClockCycle() const { return clock_cycle; }
    uint64_t Process(uint64_t addr, bool isWrite, uint64_t reqID, uint64_t time);
    Rank& getRank(uint64_t rank_id);
    Bank& getBank(uint64_t rank_id, uint64_t bank_group_id, uint64_t bank_id);
    AddressMappingConfig* getAddressMappingConfig() { return m_addressMappingConfig; }
    CommandQueue getCmdQueue() { return cmd_queue; }
    bool isNeedDrain();
    Transaction getTransactionFromId(uint64_t id);
    void DeleteTransactionInAll(uint64_t id);
    void DeleteTransactionBuffer(uint64_t id, TransactionType type);
    void DeletePending(uint64_t id, TransactionType type, uint64_t addr);
    void DeleleReturn(uint64_t id);
    void DeleteCommandFromQueue(uint64_t rank_id, uint64_t bank_group_id, uint64_t bank_id, uint64_t id);
};

#endif // __CONTROLLER__H__